<template>
    <div class="root">
        <div class="header-wrapper">
            <div class="capsual-header">
                <div class="say-hello">
                    <span>HELLO,</span>
                </div>
                <div class="info-wrapper">
                    <div class="more-info">
                        <van-popover v-model:show="showPopover" :actions="actions" @select="onSelect" :offset="popOffset">
                            <template #reference>
                                <svg @click="!showPopover" class="icon" aria-hidden="true" style="width: 27px;height: 27px;color: white;marginRight:7px;marginTop:1.7px;">
                                    <use xlink:href="#icon-gengduoneirong"></use>
                                </svg>
                            </template>
                        </van-popover>
                    </div>
                    <div class="add-icon">
                        <svg @click="showPopover=false;showSheet=!showSheet" aria-hidden="true" style="width: 31.5px;height: 30px;color: white;marginLeft:7px;">
                            <use xlink:href="#icon-tianjia"></use>
                        </svg>
                    </div>
                </div>
            </div>
            <div class="capsual-user-name">
                <span>{{userName}}</span>
            </div>
        </div>
        <div class="capsual-body">
            <div class="body-top">
                <div class="go-left" @click="turnLast()">
                    <van-icon name="arrow-left" color="#fbe4e5" size="25px"/>
                </div>
                <div class="user-capsual" style="width:100%;height:100%" @click="goIntoOpenedCapsual()">

                </div>
                <div class="go-right" @click="turnNext()">
                    <van-icon name="arrow" color="#fbe4e5" size="25px"/>
                </div>
            </div>
            <div class="body-bottom">
                <div class="capsual-shadow"></div>
            </div>
        </div>
        <div class="capsual-info-top">
            <div class="text-info">
                <div class="capsual-title">
                    <span>{{capsualTitle}}</span>
                </div>
                <div class="capsual-time">
                    <span>{{capsualTime}}</span>
                </div>
            </div>
            <div class="unlock-capsual">
                <div class="left-lock-wrapper" v-show="capNum != 0">
                    <div class="left-lock" v-show="capNum != 0 && unlockSuccess[capPointer] != 2">
                        <svg class="icon" aria-hidden="true" style="width: 39.5px;height: 30px;color: white;margin: 0 auto;">
                                <use xlink:href="#icon-lianxi2hebing-19"></use>
                        </svg>
                    </div>
                    <div class="right-unlock" v-show="capNum != 0 && unlockSuccess[capPointer] == 2">
                        <svg class="icon" aria-hidden="true" style="width: 39.5px;height: 30px;color: white;margin: 0 auto;">
                                <use xlink:href="#icon-34_kaisuo"></use>
                        </svg>
                    </div>
                </div>
                <div class="left-lock-wrapper-none" v-show="capNum == 0">
                    <div class="left-lock-none">
                        <svg class="icon" aria-hidden="true" style="width: 39.5px;height: 30px;color: white;margin: 0 auto;">
                                <use xlink:href="#icon-lianxi2hebing-19"></use>
                        </svg>
                    </div>
                </div>
            </div>
            <div class="capsual-info-middle"></div>
            <div class="capsual-info-bottom"></div>
        </div>
        <van-action-sheet v-model:show="showSheet" title="添加新胶囊">
            <div class="sheet">
                <div class="capsual-name">
                    <div class="text-title">
                        <span>胶囊标题</span>
                    </div>
                    <div class="input-capsual-name">
                        <van-form>
                            <van-field required @blur="warningNull" :error-message="errorInfo" label=" " v-model="privateCapsual.title" clearable style="backgroundColor: #fdfaf6;borderRadius: 10px;" placeholder="点击输入胶囊名称" :rules="[{required: true,validator,message:'用户名不能为空'}]"/>
                        </van-form>
                    </div>
                </div>
                <div class="target-time">
                    <div class="text-time">
                        <span>打开时间</span>
                    </div>
                    <div class="input-target-time">
                        <van-field  required label=" " @click="showCalendar = true" v-model="privateCapsual.openTime" right-icon="calendar-o" readonly style="backgroundColor: #fdfaf6;borderRadius: 10px;" placeholder="设置目标任务时间"/>
                        <van-calendar v-model:show="showCalendar" color="#55ccc9" @confirm="onConfirmCal"/>
                    </div>
                </div>
                <div class="capsual-content">
                    <div class="text-content">
                        <span>胶囊内容</span>
                    </div>
                    <div class="input-capsual-content">
                        <van-field v-model="privateCapsual.content" rows="3" autosize type="textarea" maxlength="1000" placeholder="点击输入胶囊内容" show-word-limit style="backgroundColor: #fdfaf6;borderRadius: 10px;"/>
                    </div>
                </div>
                <div class="upload-file">
                    <div class="text-up-file">
                        <span>添加图片</span>
                    </div>
                    <div class="input-file">
                        <van-uploader v-model="fileUrl" accept="image/*" upload-icon="photo-o" max-count="3" :after-read="getFileUrl"/>
                    </div>
                </div>
                <div class="upload-audio">
                    <div class="text-up-audio">
                        <span>添加音频</span>
                    </div>
                    <div class="input-audio"> <!-- 录音暂时不能用 -->
                        <van-uploader readonly accept="audio/*" @click="showLogAudio=!showLogAudio" upload-icon="volume-o" max-count="1"/>
                    </div>
                </div>
                <div class="partition-line"></div>
                <div class="ok-btn-wrapper" @click="showDia">
                    <div class="ok-btn">
                        <span>完成</span>
                    </div>
                </div>
            </div>
        </van-action-sheet>
        <van-action-sheet v-model:show="showLogAudio" title="添加音频">
            <div class="audio-wrapper">
                <div class="text-wrap">
                    <div class="audio-text">
                        <span>{{(!isStartAudio) ? "开始录音" : (!isAudioDone) ? "点击暂停" : "点击播放"}}</span>
                    </div>
                </div>
                <div class="audio-begin">
                    <div class="audio-button" @click="handleAudio">
                        <div class="inner-icon">
                            <svg class="icon icon-micro" aria-hidden="true" v-show="!isStartAudio && !isAudioDone">
                                <use xlink:href="#icon-maikefeng"></use>
                            </svg>
                            <svg class="icon icon-square" aria-hidden="true" v-show="isStartAudio && !isAudioDone">
                                <use xlink:href="#icon-checkbox-full"></use>
                            </svg>
                            <svg class="icon icon-triangle" aria-hidden="true" v-show="isStartAudio && isAudioDone && !isPlaying">
                                <use xlink:href="#icon-insert-right-full"></use>
                            </svg>
                            <svg class="icon icon-zanting" aria-hidden="true" v-show="isStartAudio && isAudioDone && isPlaying">
                                <use xlink:href="#icon-zanting"></use>
                            </svg>
                        </div>
                    </div>
                </div>
                <div class="audio-bottom">
                    <div class="audio-destroy" @click="handleDestroy">
                        <span>删除录音</span>
                    </div>
                    <div class="audio-upload" @click="uploadRecord">
                        <span>上传录音</span>
                    </div>
                </div>
            </div>
        </van-action-sheet>
        <van-dialog v-model:show="showPwdInput" :title="capNum ? capsualInfoList[capPointer].title : '' " @confirm="validatePwd" closeOnClickOverlay>
            <div style="margin: 10px 25px 10px 25px;">
                <van-field v-model="capsualInputPwd" type="password" placeholder="请输入你的胶囊密钥" style="backgroundColor: #fdfaf6;borderRadius: 10px;"/>
            </div>
        </van-dialog>
        <van-loading color="#0094ff" v-show="pwd_showLoading"/><!-- 用div包裹后放到顶部 -->
    </div>
</template>

<script setup lang="ts">
import { ref,onMounted,reactive,watch } from "vue";
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
import SplineLoader from '@splinetool/loader';
import { Vector3 } from "three"; 
import { Dialog, Notify } from 'vant';
import { useRoute,useRouter } from "vue-router";
import Recorder from "js-audio-recorder";
import { getPrivateCapsual,addPrivateCapsual,openOneCapsual,getOpenedCapsualInfo,loadImage,getImageToken,uploadFile } from "../request/api"
import { ElMessage,ElLoading } from "element-plus";
import { useGlobalData } from '../store/index'
import Compressor from 'compressorjs'

const GlobalData = useGlobalData();
const showPopover = ref<boolean>(false);
const showSheet = ref<boolean>(false);
const showCalendar = ref<boolean>(false);
const showPwdInput = ref<boolean>(false);
const showLogAudio = ref<boolean>(false);
const pwd_showLoading = ref<boolean>(false);
const isStartAudio = ref<boolean>(false);
const isAudioDone = ref<boolean>(false);
const isPlaying = ref<boolean>(false);
const router = useRouter();  //路由器和路由
const route = useRoute();
const actions = [
    {text:'查看活动'},
    {text:'我的通知'},
    {text:'关于时间胶囊'},
];
interface PrivateCapsual{
    title: string,
    content: string,
    openTime: string,
    picture: string[],
    record: string[],
}
interface GetPrivateType{
    type: string,   ///all获取所有，ready获取已经到时间但是还没有打开的，open获取打开的，close获取未到时间的
    //token?: string,
}
interface CapsualInfo{
    id: string,
    title: string,
    createdAt: string,
    openTime: string,
    success: number, //0表示没打开，1表示已经打开了
}
interface Options {
    lock: boolean,
    text: string,
    background: string,
}
const options: Options = {
    lock: true,
    text: "Loading...",
    background: 'rgba(0,0,0,0.7)'
}
var recorder = new Recorder({
    sampleBits: 8,
    sampleRate: 11025,
    numChannels: 1,
});
var privateCapsual = reactive<PrivateCapsual>({
    title: "",
    content: "",
    openTime: "",
    picture: [],
    record: [],
})
var getAllPrivate = reactive<GetPrivateType>({
    type: 'all',
})
var capsualInfoList = reactive<CapsualInfo[]>([]);
var unlockSuccess = reactive<number[]>([]);
var userName = ref<string>("");
var capsualTitle = ref<string>("您还没有创建过胶囊哟");
var capsualTime = ref<string>("xxxx.xx.xx - xxxx.xx.xx");
var popOffset = ref<[number,number]>([-7,8]);
var downX = ref<number>(); //获取鼠标点下的位置
var capsualInputPwd = ref<string>("");
var capPointer = ref<number>(0); //当前展示的是哪个胶囊
var capNum = ref<number>(0);  //用户胶囊的数量
var audioTimeStart = ref<number>(0); // 录音开始的时间
var audioTimeStop = ref<number>(0);
var errorInfo = ref<string>("");
let slider_out : HTMLElement;
let sliderBox_out : HTMLElement;
let cap : HTMLElement;
let bodyBottom : HTMLElement;
let successMoveDist_out : number;
let infoCount : number = 0;
let loading : any;
const header = {
    'Content-Type': 'multipart/form-data',
    Authorization: 'oNH82E5YqA4PZGiWhbjtDQuUSmn3yR9l', 
}
//var successDist = ref<number>(); //从起点到终点需要多少距离
//var slider_out = ref<HTMLElement>;
var fileUrl = ref([    //上传文件(文件需要设置上传数量吗)
/*     {
        url: "",
        isImage: true,
    }, */
])
const isNull = (str:string) => {
    if(str == "") return true;
    let regu = "^[ ]+$";
    let re = new RegExp(regu);
    return re.test(str);
}
const getEle = (selector:string) => document.querySelector(selector);
const beforeClose = (action:any) => new Promise((resolve)=>{
    if(action=='confirm'){
        setTimeout(() => {
            resolve(true);
            if(isNull(privateCapsual.title) || isNull(privateCapsual.content) || isNull(privateCapsual.openTime)){
                Notify({
                    type: 'warning',
                    message: '输入不可为空',
                    duration: 1000,
                })
            }else{
                addPrivateCapsual(privateCapsual).then((res:any)=>{
                    // console.log(res);
                    if (res.error_code === 0) {
                        Notify({
                            type: 'success',
                            message: '创建成功',
                            duration: 1000,
                        })
/*                         handleClosed();  //这个胶囊必然是闭合的
                        getPrivateCapsual(getAllPrivate).then((res:any) => {
                            let len = res.result.length;
                            capsualInfoList.push(res.result[len-1]);
                            capsualInfoList[len-1].createdAt = capsualInfoList[len-1].createdAt.substring(0,10);
                            capsualInfoList[len-1].openTime = capsualInfoList[len-1].openTime.substring(0,10);
                            capNum.value++;
                            capPointer.value = capNum.value - 1;
                            let idx = capPointer.value;
                            capsualTitle.value = capsualInfoList[idx].title;  //将目前显示的胶囊指向新建好的胶囊
                            capsualTime.value = capsualInfoList[idx].createdAt + ' - ' + capsualInfoList[idx].openTime;
                        }) */
                        getAllCapsual();
                    }
                })
                showSheet.value = false;
                privateCapsual.title = "";
                privateCapsual.content = "";
                privateCapsual.openTime = "";
                privateCapsual.picture.length = 0;
                privateCapsual.record.length = 0;
                fileUrl.value.length = 0;
            }
        },1000);
    }else{
        resolve(true);
    }
});
var dialogInfo = reactive<Object>({
    title: '提示',
    message: '确认完成编辑吗？\n完成编辑后就不能更改了哦',
    beforeClose,
})
const getFileUrl = (file:any) => {
    console.log(file.file);
    let rawFile = file;
    let [ fileName, fileType ] = [ file.file.name, file.file.type ];
    let loading = ElLoading.service(options);
    let compressor = new Compressor(file.file, {
        quality: 0.5,
        success: (res) => {
            console.log(res);
            let file = new File([res], fileName, { type: fileType });
            rawFile.file = file;
            uploadFile(rawFile).then((res:any) => {
                console.log(res);
                privateCapsual.picture.push(res.result);
                loading.close();
            })
        },
        error: (err) => {
            console.log(err.message);
            loading.close();
        }
    })
}
const warningNull = () => {
    if (isNull(privateCapsual.title)) {
        errorInfo.value = "标题不能为空";
    } else errorInfo.value = "";
}
const onSelect = (idx:any) => {
    //console.log(idx.text);
    if(idx.text=="查看活动"){
        router.push({ 
            name: 'activity',
        })
    }else if(idx.text=="我的通知"){
        router.push({
            name: 'notice',
        })
    }else if(idx.text=="关于时间胶囊"){
        router.push({
            name: 'about',
        })
    }else if(idx.text=="管理后台"){
        router.push({
            name: 'activityControl',
        })
    }
}
const formatDate = (date:any) => `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`;
const onConfirmCal = (value:any) => {
    //选择日历上的日期后的回调
    showCalendar.value = false;
    privateCapsual.openTime = formatDate(value);
}
const validator = (val:string) => val!="";   //检验输入是否为空
const showDia = () => {
    Dialog.confirm(dialogInfo);
}
const getOffsetX = (offset:number,min:number,max:number) => { //获取鼠标当前需要移动多少距离
    if(offset<min) offset = min;
    else if(offset>max) offset = max;
    return offset;
}
const validatePwd = () => {  //打开一个胶囊
    openOneCapsual({key:capsualInputPwd.value}).then((res:any) => {
        console.log(res);
        if(res.error_code == 0){
            Notify({
                type: 'success',
                message: '验证成功',
                duration: 1000,
            })
            let loading = ElLoading.service(options);
            getPrivateCapsual(getAllPrivate).then((res:any) => {
                console.log(res);
                let len = res.result.length;
                capNum.value = len;
                capsualInfoList.length = 0;
                unlockSuccess.length = 0;
                for(let i=0;i<len;i++){
                    capsualInfoList.push(res.result[i]);
                    capsualInfoList[i].createdAt = capsualInfoList[i].createdAt.substring(0,10)
                    capsualInfoList[i].openTime = capsualInfoList[i].openTime.substring(0,10)
                    unlockSuccess.push(capsualInfoList[i].success);
                }
                if(len > 0){
                    capsualTitle.value = capsualInfoList[0].title;
                    capsualTime.value = capsualInfoList[0].createdAt + ' - ' + capsualInfoList[0].openTime;
                }
                loading.close();
                capsualInputPwd.value = "";
                router.push({
                    name: 'content',
                    query:{
                        key: capsualInfoList[capPointer.value].id,
                    }
                })
            })
        }
    })
}
const handleStart = () => {
    recorder = new Recorder();
    recorder.start();
    audioTimeStart.value = performance.now();
}
const handlePause = () => { //暂停录音
    isPlaying.value = false;
    recorder.pause();
}
const handleResume = () => { //恢复录音
    recorder.resume();
}
const handleStop = () => { //停止录音
    isPlaying.value = false;
    recorder.stop();
    audioTimeStop.value = performance.now();
}
const handlePlay = () => { //播放录音
    isPlaying.value = true;
    recorder.play();
}
const handleDestroy = () => {  //销毁录音
    recorder.destroy();
    isStartAudio.value = false;
    isAudioDone.value = false;
    isPlaying.value = false;
}
const uploadRecord = () => { //上传录音文件
    handlePause();
    isAudioDone.value = true;
    //showLogAudio.value = false;
    const formdata = new FormData();
    const blob = recorder.getWAVBlob();
    const newblob = new Blob([blob],{type:'audio/wav'});
    const fileOfBlob = new File([newblob],new Date().getTime() + '.wav');
    formdata.append('file',fileOfBlob);
    const url = window.URL.createObjectURL(fileOfBlob);
    privateCapsual.record.push(url);
    console.log(privateCapsual.record);
}
const handleAudio = () => {
    if(!isStartAudio.value && !isAudioDone.value){
        loading = ElLoading.service(options);
        setTimeout(() => {
            isStartAudio.value = true;
            loading.close();
        },850)
        handleStart();
    }else if(isStartAudio.value && !isAudioDone.value){
        handleStop();
        isAudioDone.value = true;
    }else if(isStartAudio.value && isAudioDone.value){
        handlePlay();
        setTimeout(() => {
            isPlaying.value = false;
        }, audioTimeStop.value - audioTimeStart.value);
    }
}
const handleOpened = () => {  //处理打开后的胶囊展示效果
    slider_out.style.left = successMoveDist_out + 'px';
    renderer.domElement.style.display = "none";
    let imgBox = document.querySelector("#openedCapsule") as Node;
    let openedCapsule : any;
    if (!imgBox) {
        openedCapsule = document.createElement("img");
        openedCapsule.src = "src/assets/openedCapsule_center.png";
        openedCapsule.id = "openedCapsule";
        openedCapsule.style.width = "85%";
        openedCapsule.style.position = "relative";
        openedCapsule.style.left = "7.5%";
        cap.appendChild(openedCapsule);
    }  else return;
    //openedCapsule.style.height = "100%";
    let capRect = cap.getBoundingClientRect();
    let divHeight = capRect.height;
    console.log(divHeight);
    openedCapsule.onload = () => {   //要保证图片加载出来后再获取高度
        let imgHeight = openedCapsule.height;
        console.log(imgHeight);  //获取图片的高度，方便上移
        let diffHeight = (imgHeight - divHeight)/2; /* 获取应该上移的高度，方便 */
        openedCapsule.style.bottom = diffHeight + 'px';
    }
    bodyBottom.style.display = "none";
}
const handleClosed = () => {  //处理尚未开封的胶囊的展示效果
    slider_out.style.left = 0 + 'px';
    let imgBox = document.querySelector("#openedCapsule") as Node;
    if (imgBox) cap.removeChild(imgBox);
    renderer.domElement.style.display = "block";
    bodyBottom.style.display = "flex";
}
const turnLast = () => {
    if(!capNum.value) return;
    if(capPointer.value != 0){  //不是第一个胶囊
        let idx = --capPointer.value;
        capsualTitle.value = capsualInfoList[idx].title;
        capsualTime.value = capsualInfoList[idx].createdAt + ' - ' + capsualInfoList[idx].openTime;    
    }else{ //第一个胶囊
        capPointer.value = capNum.value - 1;
        let idx = capPointer.value;
        capsualTitle.value = capsualInfoList[idx].title;
        capsualTime.value = capsualInfoList[idx].createdAt + ' - ' + capsualInfoList[idx].openTime; 
    }
    if(!unlockSuccess[capPointer.value] || unlockSuccess[capPointer.value] == 1 || unlockSuccess[capPointer.value] == 3){
        handleClosed();
    }else if(unlockSuccess[capPointer.value] == 2){
        handleOpened();
    }
}
const turnNext = () => {
    if(!capNum.value) return;
    if(capPointer.value != capNum.value-1){
        let idx = ++capPointer.value;
        capsualTitle.value = capsualInfoList[idx].title;
        capsualTime.value = capsualInfoList[idx].createdAt + ' - ' + capsualInfoList[idx].openTime;  
    }else{
        capPointer.value = 0;
        let idx = 0;
        capsualTitle.value = capsualInfoList[idx].title;
        capsualTime.value = capsualInfoList[idx].createdAt + ' - ' + capsualInfoList[idx].openTime; 
    }
    if(!unlockSuccess[capPointer.value] || unlockSuccess[capPointer.value] == 1 || unlockSuccess[capPointer.value] == 3){
        handleClosed();
    }else if(unlockSuccess[capPointer.value] == 2){
        handleOpened();
    }
}
const confirmTime = (): boolean => { //确认是否到时间了
    let date:Date = new Date();
    let now_year:number = date.getFullYear();
    let now_month:number = date.getMonth() + 1;
    let now_date:number = date.getDate();
    //console.log(now_year + ' ' + now_month + ' ' + now_date);
    let timeArr = capsualInfoList[capPointer.value].openTime.split('-');
    let ans:boolean = false;
    if(now_year < Number(timeArr[0])){
        ans = false;
    }else if(now_year == Number(timeArr[0])){
        if(now_month < Number(timeArr[1])){
            ans = false;
        }else if(now_month == Number(timeArr[1])){
            if(now_date < Number(timeArr[2])){
                ans = false;
            }else{
                ans = true;
            }
        }else{
            ans = true;
        }
    }else{
        ans = true;
    }
    return ans;
}
const goIntoOpenedCapsual = () => {
    let idx = capPointer.value;
    if(!unlockSuccess[idx] || unlockSuccess[idx] == 1 || unlockSuccess[idx] == 3) return;  //没解锁成功就return
    else{
        router.push({
            name: 'content',
            query:{
                key: capsualInfoList[idx].id,
            }
        })
    }
}
const getAllCapsual = () => {
    getPrivateCapsual(getAllPrivate).then((res:any) => {
        console.log(res);
        let len = res.result.length;
        capNum.value = len;
        capsualInfoList.length = 0;
        unlockSuccess.length = 0;
        for(let i=0;i<len;i++){
            capsualInfoList.push(res.result[i]);
            capsualInfoList[i].createdAt = capsualInfoList[i].createdAt.substring(0,10)
            capsualInfoList[i].openTime = capsualInfoList[i].openTime.substring(0,10)
            unlockSuccess.push(capsualInfoList[i].success); //success为2的时候表示胶囊已经被打开过了
        }
        if(len > 0){
            capPointer.value = len-1;
            capsualTitle.value = capsualInfoList[len-1].title;
            capsualTime.value = capsualInfoList[len-1].createdAt + ' - ' + capsualInfoList[len-1].openTime;
        }
        cap = document.querySelector('.user-capsual') as HTMLElement;
        bodyBottom = document.querySelector('.body-bottom') as HTMLElement;
        //console.log(cap);
        cap?.appendChild(renderer.domElement);
        //renderer.domElement.style.display = "none"; 让原有关闭的胶囊隐藏，方便显示打开后的胶囊
        let slider = getEle('.left-lock-wrapper') as HTMLElement; //强制规定为HTMLElement类型而去除null类型的影响
        let sliderBox = getEle('.unlock-capsual') as HTMLElement;
        let diff = getEle('.left-lock-wrapper-none') as HTMLElement;  //灰色块占据的位置
        slider_out = slider;
        sliderBox_out = sliderBox;
        let successMoveDist = sliderBox.offsetWidth - slider.offsetWidth - diff.offsetWidth; 
        successMoveDist_out = successMoveDist;
        console.log("successMoveDist:" + successMoveDist);
         /* 保证初始上来的胶囊如果是解锁成功的，则展示开锁标志，并且放入打开后的胶囊的图片 */
        if (unlockSuccess[capPointer.value] == 2) {
            handleOpened();
        }
        const mousemoveHandler = (e:any) => {
            var e = e || e.which;
            let moveX = e.clientX ? e.clientX : e.changedTouches[0].clientX;
            let offsetX = getOffsetX(moveX - Number(downX),0,successMoveDist); //move事件不断发生，offsetX不断重新计算
            // console.log(offsetX);
            slider.style.left = offsetX + 'px';
            if(offsetX == successMoveDist){
                success();
                // console.log("解锁成功");
            } else {
                // console.log("解锁失败，回弹");
            }
            e.preventDefault();
        }
        const mousedownHandler = (e:any) => {
            var e = e || e.which;
            downX = e.clientX ? e.clientX : e.changedTouches[0].clientX;
            if(unlockSuccess[capPointer.value] != 2){  //必须是现在没有解锁才开始触发滑动，如果已经解锁了就不能触发滑动了
                document.onmousemove = mousemoveHandler;
                document.onmouseup = mouseupHandler;
                document.ontouchmove = mousemoveHandler;  //添加移动端事件
                document.ontouchend = mouseupHandler;
            }
        }
        const mouseupHandler = (e:any) => {
            let moveX = e.clientX ? e.clientX : e.changedTouches[0].clientX;
            let offsetX = getOffsetX(moveX - Number(downX),0,successMoveDist);
            if(!unlockSuccess[capPointer.value] || unlockSuccess[capPointer.value]==3 || offsetX != successMoveDist){
                console.log("回弹");
                slider.style.left = 0 + 'px';
            }
            document.onmousemove = null;
            document.onmouseup = null;
            document.ontouchmove = null;
            document.ontouchend = null;
            infoCount--;
        }
        sliderBox.onmousedown = mousedownHandler;
        sliderBox.ontouchstart = mousedownHandler;
        const success = () => {  //解锁成功
            let idx = capPointer.value;
            if(!unlockSuccess[idx]){  //还未发送
                if(infoCount < 0) infoCount = 0;
                if(infoCount == 0){ //防止多次弹窗
                    ElMessage.info("未到解锁时间哟~");
                    infoCount++;
                }
                return;
            }else if(unlockSuccess[idx] == 3){
                if(infoCount == 0){
                    ElMessage.error("解锁失败，请联系管理员");
                    infoCount++;
                }
                return;
            }else if(unlockSuccess[idx] == 1){
                showPwdInput.value = true;
            }
            sliderBox.onmousedown = null;
            document.onmousedown = null;
            document.ontouchstart = null;
            document.ontouchmove = null;
        }
    })
}
// camera
const ratio = window.innerHeight / 476.5;
const camera = new THREE.OrthographicCamera(window.innerWidth / - ratio, window.innerWidth / ratio, window.innerHeight / ratio, window.innerHeight / - ratio,  -100000, 100000);
camera.position.set(-100, -100, -100);
camera.quaternion.setFromEuler(new THREE.Euler(-2.89, -1.01, -2.93));
//camera.lookAt(new Vector3(-200,0,0));

// scene
const scene = new THREE.Scene();

// spline scene
const loader = new SplineLoader();
loader.load(
  'https://prod.spline.design/9bpIehR0VzwjW2fV/scene.splinecode',
  (splineScene) => {
    //splineScene.position.set(-320,-50,-0);
    splineScene.translateX(-310);
    splineScene.translateY(-20);
    //splineScene.rotateOnAxis(new Vector3(0,0.8,-1),-0.5);
    splineScene.rotateOnWorldAxis(new Vector3(0,0.8,-1),-0.5);
    console.log(splineScene);
    scene.add(splineScene);
/*     window.addEventListener('mousemove',(e)=>{
        let x = (e.clientX/window.innerWidth) * 2 - 1;
        let y = (e.clientY/window.innerHeight) * 2 - 1;
        console.log("!");
        let timeline = gsap.timeline();
        timeline.to(splineScene.rotation,{
            duration: 0.5,
            x: 0.5*y,
            y: 0.5*x,
        })
    }) */
  }
);

// renderer
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setAnimationLoop(animate);

// scene settings
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFShadowMap;

scene.background = new THREE.Color('#55ccc9');
renderer.setClearAlpha(0);

// orbit controls
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.125;
controls.minAzimuthAngle = Math.PI * 1.05;
controls.maxAzimuthAngle = Math.PI * 1.5;
controls.minPolarAngle = Math.PI / 1.5;
controls.maxPolarAngle = Math.PI;
//controls.enableZoom = false;   //禁用缩放
//controls.enableRotate = false;
window.addEventListener('resize', onWindowResize);
function onWindowResize() {
    camera.left = window.innerWidth / - 2;
    camera.right = window.innerWidth / 2;
    camera.top = window.innerHeight / 2;
    camera.bottom = window.innerHeight / - 2;
    camera.updateProjectionMatrix();
    renderer.setSize(window.innerWidth, window.innerHeight);
}

function animate(time:any) {
    controls.update();
    renderer.render(scene, camera);
}
watch(fileUrl,(newVal,oldVal) => {
    console.log(newVal);
    let len1 = newVal.length;
    let len2 = oldVal.length;
    if(len1 < len2){ //删除了某个图片文件
        let idx = 0;
        if(len2 == 1){ //原先只有一个
            privateCapsual.picture.pop();
        }else if(len2 == 2){
            if(newVal[idx] == oldVal[idx]){
                privateCapsual.picture.pop();
            }else{
                privateCapsual.picture.shift();
            }
        }else{
            if(newVal[idx] == oldVal[idx] && newVal[idx+1] == oldVal[idx+1]){
                privateCapsual.picture.pop();
            }else if(newVal[idx] == oldVal[idx] && newVal[idx+1] != oldVal[idx+1]){
                privateCapsual.picture.splice(1,1);
            }else{
                privateCapsual.picture.shift();
            }
        }
    }
},{
    deep:true,
})
watch(() => route.path, (newVal) => {
    console.log(newVal);
    if (newVal == "/capsual") {
        getAllCapsual();
    }
})
onMounted(()=>{
/*     getImageToken({username:'1691637805', password:'wlh9542559'}).then((res:any) => { 随时调用，不用先用死的
        console.log(res);
        header.Authorization = res.data.token;
    }) */
    let loading = ElLoading.service(options);
    setTimeout(() => { /* 增加缓冲，保证胶囊加载出来 */
        loading.close();
    }, 1000);
    userName.value = GlobalData.nickName;
    if(GlobalData.role === "admin") actions.push({text:'管理后台'});
    getAllCapsual();
})
</script>
<style> /*修改组件的css记得单独建一个style标签*/
    :root{
        --van-action-sheet-max-height: 93% !important;
        --van-uploader-size: 40px !important; 
        --van-uploader-icon-size: 20px !important; 
        --van-field-label-width: 0px !important;
    }
</style>
<style lang="less" scoped>
    .root{
        background-color: #55ccc9;
        display: flex;
        flex-direction: column;
        position: fixed; /*为了使用height100% */
        height: 100%;
        width: 100%;
        /*height: 1200px;*/
        justify-content: space-between;
        .header-wrapper{
            display: flex;
            flex-direction: column;
            margin: 42px 24px 0 24px;
            .capsual-header{
                display: flex;
                justify-content: space-between;
                .say-hello{
                    font-size: 32px;
                    font-weight: 600;
                    color: white;
                }
                .info-wrapper{
                    display: flex;
                }
            }
            .capsual-user-name{
                font-size: 24px;
                font-weight: 600;
                color: white;
            }
        }
        .capsual-body{
            display: flex;
            flex-direction: column;
            margin: 20px 20px 0px 20px;
            height: 45%;
            .body-top{
                display: flex;
                /*height: 360px;*/
                height: 95%;
                justify-content: space-between;
                align-items: center;
                .user-capsual{
                    position: relative;
                    transform: rotateX(10deg);
                }

            }
            .body-bottom{
                display: flex;
                /*height: 10px;*/
                height: 5%;
                margin-bottom: 10px;
                justify-content: center;
                .capsual-shadow{
                    width: 147px;
                    height: 21px;
                    background: radial-gradient(88.1% 88.1% at 50% 50%, #2E9BA2 0%, #48ADAC 45.31%, #67D0C8 100%);
                    filter: blur(10px);
                }
            }
        }
        .capsual-info-top{
            display: flex;
            flex-direction: column;
            width: 85%;
            height: 25%;
            margin: 0 auto;
            margin-top: 20px;
            margin-bottom: 25px;
            background-color: #fff;
            border-radius: 18px;
            z-index: 4;
            .text-info{
                display: flex;
                flex-direction: column;
                margin: 20px 30px;
                z-index: 4;
                .capsual-title{
                    font-size: 24px;
                    font-weight: 500;
                    margin-bottom: 5px;
                }
                .capsual-time{
                    font-size: 16px;
                    font-weight: 400;
                    color: #929292;
                }
            }
            .unlock-capsual{
                position: relative;
                width: 86%;
                margin: 0 auto;
                height: 30%;
                border-radius: 50px;
                background-color: #F2F5F4;
                z-index: 4;
                .left-lock-wrapper{
                    position: absolute;
                    width: 98px;
                    height: 100%;
                    left: 0px;
                    right: 0px;
                    transition: left 0.1s;
                    background: linear-gradient(154.59deg, #EECDA3 16.1%, #EF8BA1 250.72%);
                    border-radius: 52px;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                }
                .left-lock-wrapper-none{
                    position: absolute;
                    width: 98px;
                    height: 100%;
                    left: 0px;
                    right: 0px;
                    transition: left 0.1s;
                    background: linear-gradient(154.59deg, #c1bab1 16.1%, #d69ba8 250.72%);
                    border-radius: 52px;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                }
            }
            .capsual-info-middle{
                position: absolute;
                z-index: 3;
                background-color: rgba(255, 255, 255, 0.7);
                width: 79%;
                height: 25%;
                bottom: 37px;
                left: 10.5%;
                border-radius: 18px;
            }
            .capsual-info-bottom{
                position: absolute;
                z-index: 2;
                background-color: rgba(255, 255, 255, 0.3);
                border-radius: 18px;
                width: 73%;
                left: 13.5%;
                height: 25%;
                bottom: 49px;
            }
        }
        .sheet{
            display: flex;
            flex-direction: column;      
            .capsual-name{
                margin: 0 32px 0 32px;
                .text-title{
                    font-size: 16px;
                    font-weight: 400;
                    margin-bottom: 10px;
                    margin-left: 2px;
                }
                .input-capsual-name{
                    margin-bottom: 20px;
                }
            }
            .target-time{
                margin: 0 32px 0 32px;
                .text-time{
                    font-size: 16px;
                    font-weight: 400;
                    margin-bottom: 10px;
                    margin-left: 2px;
                }
                .input-target-time{
                    margin-bottom: 20px;
                }
            }
            .capsual-content{
                margin: 0 32px 0 32px;
                .text-content{
                    font-size: 16px;
                    font-weight: 400;
                    margin-bottom: 10px;
                    margin-left: 2px;
                }
                .input-capsual-content{
                    margin-bottom: 20px;
                }
            }
            .upload-file{
                margin: 0 32px 0 32px;
                .text-file{
                    font-size: 14px;
                    font-weight: 400;
                }
                .input-file{
                    margin-top: 10px;
                }
            }
            .upload-audio{
                margin: 0 32px 0 32px;
                .text-audio{
                    font-size: 14px;
                    font-weight: 400;
                }
                .input-audio{
                    margin-top: 10px;
                    margin-bottom: 15px;
                }
            }
            .partition-line{
                background-color: #f7f8fa;
                height: 8px;
            }
            .ok-btn-wrapper{
                height: 48.8px;
                display: flex;
                justify-content: center;
                align-items: center;
                .ok-btn{
                    font-size: 16px;
                    font-weight: 400;
                }
            }
        }
        .audio-wrapper{
            display: flex;
            height: 180px;
            flex-direction: column;
            .text-wrap{
                display: flex;
                justify-content: center;
                .audio-text{
                    margin-top: 6px;
                    //margin: 0 auto;
                    font-size: 16px;
                    font-weight: 400;
                    color: #929292
                }
            }
            .audio-begin{
                height: 100px;
                display: flex;
                justify-content: center;
                margin-top: 20px;
                .audio-button{
                    background-color: rgb(49, 189, 236);
                    width: 70px;
                    height: 70px;
                    border-radius: 50%;
                    box-shadow: 3px 3px 10px aqua;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    .inner-icon{
                        width: 60%;
                        height: 60%;
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        .icon-micro{
                            width: 27px;
                            height: 27px;
                        }
                        .icon-square{
                            width: 27px;
                            height: 27px;
                            color: white;
                        }
                        .icon-triangle{
                            width: 35px;
                            height: 35px;
                            color: white;
                        }
                        .icon-zanting {
                            width: 28px;
                            height: 28px;
                            color: white; 
                        }
                    }
                }
            }
            .audio-bottom{
                display: flex;
                .audio-destroy{
                    width: 50%;
                    height: 30px;
                    font-size: 16px;
                    line-height: 30px;
                    text-align: center;
                    color: red;
                    border-right: 1px rgb(223, 201, 201) solid;
                    border-top: 1px rgb(223, 201, 201) solid;
                }
                .audio-upload{
                    width: 50%;
                    font-size: 16px;
                    line-height: 30px;
                    text-align: center;
                    border-top: 1px rgb(223, 201, 201) solid;
                }
            }
        }
    }
</style>